<?php

/**
 * Model che rappresenta un agente nel DB.
 */
class VariazioneArticolo extends StdModel
{

	private static $singleton = NULL;

	/**
	 * Ritorna una istanza globale di questo model.
	 * @return mixed La istanza globale.
	 */
	public static function getInstance()
	{
		if(self::$singleton == NULL)
			self::$singleton = new VariazioneArticolo();
		return self::$singleton;
	}

	/*
	 * Specifiche attributi del tipo del Model rappresentato da questa classe
	 */
	public $attribTableName = "VariazioneArticolo";
	public $attribLabel = "Codice";
	public $attribNames = array(STD_ID, "Codice", "idArticolo", "DettagliTecnici", "QuantitaListino", "PrezzoDiListino");
	public $attribExcludeFromAdd = array(STD_ID);
	public $attribExcludeFromEdit = array(STD_ID, "idArticolo");
	public $attribLongNames = array(STD_ID => "ID", "Codice" => "Codice", "idArticolo" => "Articolo base",
		"DettagliTecnici" => "Dettagli Tecnici", "QuantitaListino" => "Quantit&agrave; di listino", "PrezzoDiListino" => "Prezzo di listino &euro;");
	public $attribIsImportant = array(STD_ID => 2, "Codice" => 1, "idArticolo" => 1, "DettagliTecnici" => 1,
		"QuantitaListino" => 1, "PrezzoDiListino" => 1);
	public $attribIsNumeric = array(STD_ID => true, "Codice" => false, "idArticolo" => true, "DettagliTecnici" => false,
		"QuantitaListino" => true, "PrezzoDiListino" => true);
	public $attribIsForeignKey = array(STD_ID => false, "Codice" => false, "idArticolo" => "Articoli", "DettagliTecnici" => false,
		"QuantitaListino" => false, "PrezzoDiListino" => false);

	/*
	 * Specifiche per gli elementi form associati agli attributi
	 */
	private static $attribHTMLFormValue = array(STD_ID => FORM_HIDDEN, "Codice" => FORM_TEXT, "idArticolo" => FORM_HIDDEN,
		"DettagliTecnici" => FORM_TEXT, "QuantitaListino" => FORM_TEXT, "PrezzoDiListino" => FORM_TEXT);
	private static $attribHTMLFormIsMandatory = array(STD_ID => true, "Codice" => true, "idArticolo" => true, "DettagliTecnici" => true,
		"QuantitaListino" => true, "PrezzoDiListino" => true);

	/**
	 * Restituisce l'HTML per creare un campo di un form adatto a contenere il
	 * valore dell'attribbuto passato. Questo campo di testo sarà vuoto e dovrà
	 * servire per la creazione di una nuova istanza in DB di questo model.
	 * @param string $attribName Nome dell'attributo su cui creare il campo.
	 * @return string Stringa contenente l'HTML dell'elemento creato.
	 */
	public function getAddFormCodeFromAttribute($db,$attribName)
	{
		if(!isset(self::$attribHTMLFormValue[$attribName]) || $attribName == STD_ID)
			return "";
		$defval = NULL;
		if($attribName == "PrezzoDiListino")
			$defval = "0.0";
		elseif($attribName == "QuantitaListino")
			$defval = "1";
		switch(self::$attribHTMLFormValue[$attribName])
		{
			case FORM_TEXT: return ModelUtils::getTextFormElement($attribName, $defval, self::$attribHTMLFormIsMandatory[$attribName], 0);
			case FORM_HIDDEN: return ModelUtils::getHiddenFormElement($attribName, isset($this->dataTupla[$attribName]) && $this->dataTupla[$attribName] != NULL ? $this->dataTupla[$attribName] : "", self::$attribHTMLFormIsMandatory[$attribName]);
			//case FORM_NUMERIC: return ModelUtils::getNumericFormElement($attribName, "1", "1", NULL, self::$attribHTMLFormIsMandatory[$attribName], 0);
			default: return "";
		}
	}

	/**
	 * Restituisce l'HTML per creare un campo di testo adatto a contenere il
	 * valore dell'attribbuto passato. Questo campo di testo conterrà il valore
	 * attualmente assunto da questo attributo in questa tupla.
	 * @param DatabaseManager $db Database su cui effettuare una possibile
	 * interrogazione.
	 * @param string $attribName Nome dell'attributo di cui creare il codice.
	 * @return string Il codice HTML dell'elemento form corrispondente.
	 */
	public function getEditFormCodeFromAttribute($db, $attribName)
	{
		if(!isset(self::$attribHTMLFormValue[$attribName]))
			return "";
		$size = NULL;
		if($attribName == "PrezzoDiListino" || $attribName == "QuantitaListino")
			$size = 0;
		switch(self::$attribHTMLFormValue[$attribName])
		{
			case FORM_TEXT: return ModelUtils::getTextFormElement($attribName, $this->dataTupla[$attribName], self::$attribHTMLFormIsMandatory[$attribName], $size);
			case FORM_HIDDEN: return ModelUtils::getHiddenFormElement($attribName, isset($this->dataTupla[$attribName]) && $this->dataTupla[$attribName] != NULL ? $this->dataTupla[$attribName] : "", self::$attribHTMLFormIsMandatory[$attribName]);
			//case FORM_NUMERIC: return ModelUtils::getNumericFormElement($attribName, $this->dataTupla[$attribName], "1", NULL, self::$attribHTMLFormIsMandatory[$attribName]);
			default: return "";
		}
	}

	/**
	 * Costruttore che acquisisce l'array dei valori associativi.
	 * @param type $data L'array associativo a cui inizializzare questa istanza.
	 */
	public function __construct($data = NULL)
	{
		parent::__construct($data);
	}

	/**
	 * Crea una nuova istanza della sottoclasse specializzante.
	 * @param array $data I dati passati da cui recuperare i valori.
	 * @return mixed Una nuova instanza della sottoclasse specializzante.
	 */
	public function createNew($data)
	{
		//const joinSelect ="Articolo.*, VariazioneArticolo.ID AS IDAssoc, Codice, idArticolo, DettagliTecnici, PrezzoDiListino";
		//se l'array contiene già le informazioni sull'articolo lo si crea direttamente anch'esso
		if(isset($data["IDAssoc"]))
		{
			$art = Articolo::getInstance()->createNew($data);
			$data["ID"] = $data["IDAssoc"];
			$res = new VariazioneArticolo($data);
			$res->chachedArticolo = $art;
			$res->chachedArticolo->cutLongStrings($this->cutDataLabels);
			return $res;
		}
		else
			return new VariazioneArticolo($data);
	}

	/**
	 * Duplica tutte le tuple di questo model con l'id articolo specificato
	 * ed imposta nelle nuove tuple come id articolo il valore idArticolo
	 * passato.
	 * @param DatabaseManager $db Database da interrogare.
	 * @param int $idVecchioArticolo ID vecchio articolo delle tuple da
	 * duplicare.
	 * @param int $idNuovoArticolo ID nuovo articolo da impostare nelle nuove
	 * tuple.
	 */
	public function duplicateFromIDArticolo($db,$idVecchioArticolo,$idNuovoArticolo)
	{
		return $db->AddRecordsWithSELECT($this->attribTableName, "Codice, idArticolo, DettagliTecnici, QuantitaListino, PrezzoDiListino",
				"SELECT Codice, ".$idNuovoArticolo.", DettagliTecnici, QuantitaListino, PrezzoDiListino FROM ".$this->attribTableName." WHERE idArticolo = ".$idVecchioArticolo);
	}
	
	/**
	 * Carica dal DB una lista di istanze di questa sottoclasse caricate con i
	 * valori delle tuple trovate secondo le specifiche passate.
	 * @param DatabaseManager $db Database da cui prelevare le tuple.
	 * @param int $limitMin Limite basso da cui iniziare a prelevare tuple, o
	 * NULL per non usare i limiti.
	 * @param int $limitMax Limite alto a cui fermarsi di prelevare tuple, o
	 * NULL per non usare i limiti.
	 * @param string $orderBy Ordinamento con cui prelevare le tuple, o "" per
	 * non usare alcun ordinamento.
	 * @return array L'array delle nuove istanze create a partire dai valori
	 * trovati nel DB o NULL nel caso qualcosa sia andato storto.
	 */
	public function getListFromDBByIDArticolo($db, $idArticolo, $limitMin = NULL , $limitMax = NULL, $orderBy = "")
	{
		$limits = ($limitMin === NULL || $limitMax === NULL ? "" : ($limitMin.", ".($limitMax-$limitMin)) );
		$rs = $db->EnumerateTableStart($this->attribTableName, $orderBy,"idArticolo = ".$idArticolo,$limits);
		if($rs == FALSE)
			return NULL;
		$retarr = array();
		while($db->EnumerateTableNext($rs))
			$retarr[] = $this->createNew($db->EnumerateTableGetValues($rs));
		return $retarr;
	}

	/**
	 * Metodo che restituisce una etichetta che rappresenta il valore di un
	 * attributo: nella sua versione di default ritorna esattamente il valore
	 * associato a quell'attributo, ma è possibile implementarlo nelle
	 * sottoclassi per specificare opportuni comportamenti, come ad esempio di
	 * non far stampare un numero che rappresenta una chiave esterna, ma invece
	 * una etichetta della tupla ad essa associata.
	 * @param DatabaseManager $db Database su cui poter effettuare una possibile
	 * interrogazione.
	 * @param string $attrib Attributo di cui stampare l'etichetta del valore.
	 * @return string Il valore associato all'attributo o NULL se l'attributo
	 * non è stato trovato.
	 */
	public function getDataLabel($db, $attrib)
	{
		if($attrib == "idArticolo" && !$this->showRealValues_Enabled)
			return $this->getArticolo($db)->getLabel();
		return parent::getDataLabel($db, $attrib);
	}

	const joinTable = "VariazioneArticolo LEFT JOIN Articolo ON VariazioneArticolo.idArticolo = Articolo.ID";
	const joinSelect ="Articolo.*, VariazioneArticolo.ID AS IDAssoc, Codice, idArticolo, DettagliTecnici, QuantitaListino, PrezzoDiListino";

	private $chachedArticolo = NULL;

	/**
	 * Ritorna una istanza di Articolo corrispondente alla chiave esterna
	 * "idArticolo" di questa tupla.
	 * @param DatabaseManager $db Database da interrogare.
	 * @return Articolo L'instanza creata o NULL in caso di errore.
	 */
	public function getArticolo($db)
	{
		$idag = isset($this->dataTupla["idArticolo"]) ? $this->dataTupla["idArticolo"] : NULL;
		if($idag != NULL && $idag > 0)
		{
			if($this->chachedArticolo == NULL || $this->chachedArticolo->dataTupla[STD_ID] != $idag)
			{
				$this->chachedArticolo = Articolo::getInstance()->getFromDB($db, $this->dataTupla["idArticolo"]);
				$this->chachedArticolo->cutLongStrings($this->cutDataLabels);
				return $this->chachedArticolo;
			}
			else
				return $this->chachedArticolo;
		}
		return NULL;
	}

	/**
	 * Carica dal DB una lista di istanze di questa sottoclasse caricate con i
	 * valori delle tuple trovate secondo le specifiche passate.
	 * @param DatabaseManager $db Database da cui prelevare le tuple.
	 * @param int $limitMin Limite basso da cui iniziare a prelevare tuple, o
	 * NULL per non usare i limiti.
	 * @param int $limitMax Limite alto a cui fermarsi di prelevare tuple, o
	 * NULL per non usare i limiti.
	 * @param string $orderBy Ordinamento con cui prelevare le tuple, o "" per
	 * non usare alcun ordinamento.
	 * @return array L'array delle nuove istanze create a partire dai valori
	 * trovati nel DB o NULL nel caso qualcosa sia andato storto.
	 */
	public function getListFromDB($db, $limitMin, $limitMax, $orderBy, $cond = "")
	{
		$limits = ($limitMin === NULL || $limitMax === NULL ? "" : ($limitMin.", ".($limitMax-$limitMin)) );
		//SELECT Articolo.*, AziendaRappresentata.Ragsoc, AziendaRappresentata.Indirizzo, AziendaRappresentata.CAP, AziendaRappresentata.Citta, AziendaRappresentata.Provincia, AziendaRappresentata.Stato FROM Articolo LEFT JOIN AziendaRappresentata ON Articolo.idAziendaRappresentata = AziendaRappresentata.ID
		$rs = $db->EnumerateTableStartExt(self::joinSelect, self::joinTable, $orderBy,$cond,$limits);
		if($rs == FALSE)
			return NULL;
		$retarr = array();
		while($db->EnumerateTableNext($rs))
			$retarr[] = $this->createNew($db->EnumerateTableGetValues($rs));
		return $retarr;
	}

	/**
	 * Cerca una serie di tuple nel DB e ritorna tante istanze della sottoclasse
	 * specializzante, quante sono le rispettive tuple trovate con i rispettivi
	 * valori caricati entro i limiti specificati.
	 * @param DatabaseManager $db Database da cui prelevare le tuple.
	 * @param string $paramName Nome dell'attributo su cui effettuare la
	 * ricerca.
	 * @param string $paramValue Valore che l'attributo deve assumere per
	 * includere la sua rispettiva tupla.
	 * @param int $limitMin Limite basso da cui iniziare a prelevare tuple, o
	 * NULL per non usare i limiti.
	 * @param int $limitMax Limite alto a cui fermarsi di prelevare tuple, o
	 * NULL per non usare i limiti.
	 * @param string $orderBy Ordinamento con cui prelevare le tuple, o "" per
	 * non usare alcun ordinamento.
	 * @return array L'array delle nuove istanze create a partire dai valori
	 * trovati nel DB o NULL nel caso qualcosa sia andato storto.
	 */
	public function searchByParam($db, $paramName, $paramValue, $limitMin, $limitMax, $orderBy)
	{
		if(!isset($this->attribIsNumeric[$paramName]))
			return NULL;
		$limits = ($limitMin === NULL || $limitMax === NULL ? "" : ($limitMin.", ".($limitMax-$limitMin)) );
		$cond = NULL;
		if($paramName == "idArticolo")
		{
			//se il parametro della ricerca è idAziendaRappresentata, allora la ricerca si effettua sulla ragione sociale dell'azienda
			$cond = "DescrizioneBreve LIKE '%".ModelUtils::escape_sq_for_SQL($paramValue)."%'";
		}
		else
		{
			//caso contrario si effettua sul parametro specificato come di norma
			$paramIsNumeric = $this->attribIsNumeric[$paramName];
			if($paramName == STD_ID)
				$paramName = $this->attribTableName.".".STD_ID;
			$cond = ($paramIsNumeric ? $paramName." = ".$paramValue : $paramName." LIKE '%".ModelUtils::escape_sq_for_SQL($paramValue)."%'");
		}
		$rs = $db->EnumerateTableStartExt(self::joinSelect, self::joinTable, $orderBy, $cond, $limits );
		if($rs == FALSE)
			return NULL;
		$retarr = array();
		while($db->EnumerateTableNext($rs))
			$retarr[] = $this->createNew($db->EnumerateTableGetValues($rs));
		return $retarr;
	}

	/**
	 * Restituiscce il numero di tuple del risultato della ricerca.
	 * @param DatabaseManager $db Database da interrogare.
	 * @param string $searchAttrib Nome dell'attributo su cui effettuare la
	 * ricerca.
	 * @param string $searchVal Valore che l'attributo deve assumere per far
	 * contare la propria tupla.
	 * @return int Restituisce il numero di tuple trovate o FALSE in caso di
	 * errore.
	 */
	public function getRecordsNumOfSearchResult($db,$searchAttrib,$searchVal)
	{
		if(!isset($this->attribIsNumeric[$searchAttrib]))
			return FALSE;
		$cond = NULL;
		if($searchAttrib == "idArticolo")
		{
			//se il parametro della ricerca è idAziendaRappresentata, allora la ricerca si effettua sulla ragione sociale dell'azienda
			$cond = "DescrizioneBreve LIKE '%".ModelUtils::escape_sq_for_SQL($searchVal)."%'";
		}
		else
		{
			//caso contrario si effettua sul parametro specificato come di norma
			$paramIsNumeric = $this->attribIsNumeric[$searchAttrib];
			if($searchAttrib == STD_ID)
				$searchAttrib = $this->attribTableName.".".STD_ID;
			$cond = ($paramIsNumeric ? $searchAttrib." = ".$searchVal : $searchAttrib." LIKE '%".ModelUtils::escape_sq_for_SQL($searchVal)."%'");
		}
		return $db->GetRecordsNum(self::joinTable,$cond);
	}

}

?>
